package com.hejia.alauda.service;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.joda.time.DateTime;
import org.springframework.stereotype.Service;

import com.hejia.alauda.entity.Parameter;
import com.hejia.alauda.entity.Product;
import com.hejia.alauda.entity.Product.Category;
import com.hejia.alauda.entity.Warning;
import com.hejia.alauda.entity.WarningSetting;
import com.hejia.alauda.entity.example.WarningExample;
import com.hejia.alauda.persistence.mybatis.WarningMapper;
import com.hejia.alauda.utils.Pager;
import com.hejia.hermes.entity.SMS;
import com.hejia.hermes.service.SMSService;

@Service
public class WarningServiceImpl implements WarningService {

	private static final Log Logger = LogFactory.getLog(WarningServiceImpl.class);
	
	private static final String SEND_WARNING_CODE_QUARTER = "SendWarningCodeQuarter"; // 发送预警编码季享
	private static final String SEND_WARNING_CODE_MONTH = "SendWarningCodeMonth"; // 发送预警编码月享
	private static final String SEND_WARNING_CODE_ROOKIE = "SendWarningCodeRookie"; // 发送预警编码新手
	private static final String SEND_WARNING_CODE_CURRENT = "SendWarningCodeCurrent"; // 发送预警编码钱滚翻
	private static final String SEND_WARNING_CODE_HALF_A_YEAR = "SendWarningCodeHalfAYear"; // 发送预警编码双季
	private static final String SEND_WARNING_CODE_YEAR = "SendWarningCodeYear"; // 发送预警编码年享
	
	@Resource
	private WarningMapper warningMapper;

	@Resource(name = "sendSMS")
	private SMSService smsService;
	
	@Resource
	private ConfigureService configureService;
	
	@Resource
	private ProductService productService;

	@Override
	public void sendNotPresellWarning(Category category) {
		
		// 排期预售预警是否启用
		if (!enablePresellWarning()) {
			return;
		}

		// 发送预警
		if (Category.MONTH.equals(category)) {
			sendProductWarning(category, false, SEND_WARNING_CODE_MONTH);
		} else if (Category.QUARTER.equals(category)) {
			sendProductWarning(category, false, SEND_WARNING_CODE_QUARTER);
		} else if (Category.CURRENT.equals(category)) {
			sendProductWarning(category, false, SEND_WARNING_CODE_CURRENT);
		} else if (Category.HALF_A_YEAR.equals(category)) {
			sendProductWarning(category, false, SEND_WARNING_CODE_HALF_A_YEAR);
		} else if (Category.YEAR.equals(category)) {
			sendProductWarning(category, false, SEND_WARNING_CODE_YEAR);
		} else {
			Logger.error("不支持预警产品类别：" + category);
		}
	}

	/**
	 * 发送无产品可售预警
	 * @param category	产品类别
	 * @param rookie	是否新手标
	 * @param code	发布预警结果获取编码
	 */
	private void sendProductWarning(Product.Category category, boolean rookie, String code) {
		
		// 是否已发送预警
		if (this.isSentWarning(category, rookie, code)) {
			return;
		}

		// 发送预警
		String message = "无产品可售，请及时发售";
		if (rookie) {
			message = "新手标" + message;
		} else {
			message = category.getName() + message;
		}
		
		List<Warning> warnings = this.findWarnings();
		for (Warning warning : warnings) {
			try {
				this.sendWarning(warning, message);
			} catch (Exception e) {
				Logger.error("无产品可售预警失败", e);
			}
		}

		// 设置发送预警标记
		updateSentProductWarningMarker(category, rookie, code);
		
	}

	/**
	 * 已发送无可售产品标记
	 * @param category	产品类别
	 * @param rookie	是否新手标
	 * @param code	发布预警结果获取编码
	 */
	private void updateSentProductWarningMarker(Category category, boolean rookie, String code) {
		
		Product product = productService.findLastProdutc(category, rookie);
		Parameter parameter = this.configureService.getParameter(
				Parameter.Category.Warning, code);
		
		DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		if (parameter == null) {
			parameter = new Parameter();
			parameter.setCategory(Parameter.Category.Warning);
			parameter.setCode(code);
			parameter.setValue(format.format(product.getCreateDate()));
			parameter.setMemo("已发送无可售产品标记");
			this.configureService.saveParameter(parameter);
		} else {
			parameter.setValue(format.format(product.getCreateDate()));
			this.configureService.updateParameter(parameter);
		}
	}

	/**
	 * 是否已发布预警
	 * @param category	产品类别
	 * @param rookie	是否新手标
	 * @param code	发布预警结果获取编码
	 * @return
	 */
	private boolean isSentWarning(Category category, boolean rookie, String code) {

		Product product = productService.findLastProdutc(category, rookie);
		
		// 无产品不预警
		if (product == null) {
			return true;
		}
		
		// 判断发布预警时最后一条产品创建时间与刚获取的是否一致
		Parameter parameter = this.configureService.getParameter(
				Parameter.Category.Warning, code);
		if(parameter == null || StringUtils.isEmpty(parameter.getValue())){
			return false;
		}
		
		DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		if(format.format(product.getCreateDate()).equals(parameter.getValue())){
			return true;
		}
		return false;
	}

	/**
	 * 是否启用排期预售预警
	 * @return true - 启用，false - 未启用
	 */
	private boolean enablePresellWarning() {
		
		WarningSetting setting = this.configureService.getWarningSetting();
		if (setting == null 
		|| setting.getPresellSwitch() == null 
		|| !setting.getPresellSwitch()) {
			return false;
		}
		return true;
	}

	/**
	 * 发送预警
	 * 
	 * @param warning
	 */
	private void sendWarning(Warning warning, String message) {

		if (warning.getWarntype() == Warning.Warntype.AllDay 
			|| (warning.getWarntype() == Warning.Warntype.NotAllDay && isInWorkTime())) {
			Logger.debug("发送预警短信");
			SMS sms = new SMS();
			sms.setMobile(warning.getPhoneNum());
			sms.setMessage(message);
			sms.setChannel("builtin_notice");
			smsService.sendSMS(sms);
		}
	}

	/**
	 * 是否在工作时间
	 * 
	 * @return true - 是， false - 否
	 */
	private boolean isInWorkTime() {

		DateTime now = new DateTime();
		int week = now.dayOfWeek().get();
		if (week == 6 || week == 7) {
			return false;
		}

		if (now.getHourOfDay() < 9 || now.getHourOfDay() >= 17) {
			return false;
		}

		return true;
	}

	private List<Warning> findWarnings() {
		Pager<Warning> pager = new Pager<>();
		pager.setPageSize(100);
		WarningExample example = new WarningExample();
		return warningMapper.selectByExample(example, pager);
	}

	@Override
	public void sendNoneRookiePresellWarning() {
		
		// 无产品预警是否启用
		if (!enablePresellWarning()) {
			return;
		}
		
		sendProductWarning(null, true, SEND_WARNING_CODE_ROOKIE);
	}
}
